Hi Friends! artikel kali ini adalah hasil riset Ethic Ninja assisted by AI Agent terhadap race condition pada net/http: bagaimana pembatasan ukuran request body dapat memicu denial-of-service pada aplikasi Go tertentu.
Sekilas tentang kerentanannya
· Pada 10 November 2026, tim Go merilis versi 1.27.4 dan 1.26.11 dengan perbaikan untuk 12 CVE. Sebelas di antaranya berkaitan dengan keamanan saat proses build, khususnya penggunaan cgo. Satu CVE lainnya, CVE-2026-97054, berada pada paket net/http dan menjadi fokus pengujian kami karena dapat dipicu melalui request HTTP pada konfigurasi tertentu.
· Masalah muncul ketika aplikasi membatasi ukuran request body dengan MaxBytesReader atau MaxBytesHandler. Saat batas tersebut terlewati, net/http dapat mengubah header respons pada saat handler lain juga sedang mengakses header yang sama. Kedua operasi ini berjalan tanpa sinkronisasi yang memadai.
· Pada kondisi tertentu, dua penulisan ke map yang sama memicu error fatal `concurrent map writes`. Berbeda dari request yang hanya gagal diproses, kejadian ini dapat menghentikan seluruh proses server. Akibatnya, layanan tidak tersedia bagi pengguna lain.
· Dalam lab Ethic Ninja, race detector menemukan masalah ini pada handler HTTP biasa maupun kombinasi httputil.ReverseProxy dengan MaxBytesHandler. Pengujian pada Go 1.25.1 dan 1.26.10 juga memperlihatkan proses yang crash. Sebagai pembanding, Go 1.27.4 tetap berjalan setelah serangkaian pengujian yang sama.
· Advisory OSV mencatat kerentanan ini telah ada sejak awal implementasi yang terdampak (Introduced: 0). Saat pengujian dilakukan, skor CVSS dari NVD belum tersedia, CVE ini belum tercatat di CISA KEV, dan kami belum menemukan PoC publik. Status tersebut dapat berubah setelah artikel diterbitkan.
Mengapa update Go kali ini penting?
Rilis keamanan Go pada 11 November mencakup dua kelompok masalah. Sebagian besar berkaitan dengan proses build: paket cgo yang tidak tepercaya dapat menyalahgunakan flag compiler atau linker. Sementara itu, CVE-2026-97054 menarik karena menyasar server HTTP yang sudah berjalan, tanpa perlu melibatkan proses build.
Kerentanan ini tidak berarti semua aplikasi Go dapat langsung dijatuhkan. Kondisinya lebih spesifik: aplikasi menggunakan HTTP/1 dan pembatas request body, sementara proses membaca body berlangsung bersamaan dengan penulisan header respons. Pola seperti ini bisa muncul pada API gateway, reverse proxy, dan handler yang memproses request secara concurrent.
Problemnya adalah dua goroutine menulis header yang sama
Saat request body melebihi batas, maxBytesReader.Read dapat memanggil response.requestTooLarge(). Pada versi yang rentan, fungsi tersebut ikut mengubah header `Connection: close`. Persoalannya, fungsi ini bisa dijalankan dari goroutine pembaca body, bukan dari alur yang seharusnya mengelola penulisan respons.
func (w *response) requestTooLarge() {
w.closeAfterReply = true
w.requestBodyLimitHit = true
if !w.wroteHeader {
w.Header().Set("Connection", "close") // <- map write,
} // goroutine mana pun
}
Patch resmi mengubah status pembatasan body menjadi atomic.Bool dan memindahkan penanganan header `Connection: close` ke chunkWriter.writeHeader. Dengan demikian, perubahan header tidak lagi dilakukan dari goroutine pembaca body. Perubahan ini terlihat pada commit yang kami sertakan di referensi.

Gambar 2. Cuplikan patch resmi net/http: status request body disimpan secara atomic, sedangkan perubahan header dipindahkan ke jalur penulisan respons.
Lingkungan pengujian Ethic Ninja
Kami menyiapkan tiga versi Go: 1.25.1, 1.26.10 (sebelum patch), dan 1.27.4 (sesudah patch). Dua bentuk server diuji, yakni handler HTTP sederhana dan kombinasi ReverseProxy dengan MaxBytesHandler. Tujuannya bukan hanya mencari race condition, tetapi juga memastikan apakah masalah tersebut benar-benar dapat menghentikan layanan.

Gambar 3. Versi Go yang dipakai dalam lab dan identitas advisory kerentanan.
Bukti pertama: race detector menemukan masalah
Kami menjalankan aplikasi dengan fitur race detector milik Go (`-race`). Fitur ini membantu mendeteksi akses memory yang berpotensi bertabrakan, tanpa harus menunggu proses crash. Kode aplikasi yang diuji tetap sama; hanya metode build-nya yang berbeda.

Gambar 4. Race detector pada Go 1.26.10 menunjukkan akses bersamaan ke header respons dari requestTooLarge dan handler.
Setelah pola pada handler sederhana terbukti, pengujian dilanjutkan ke skenario yang lebih dekat dengan penggunaan nyata: reverse proxy yang meneruskan request body ke upstream.

Gambar 5. Race detector juga menemukan masalah pada kombinasi httputil.ReverseProxy dan MaxBytesHandler.

Gambar 6. Pada Go 1.27.4, pengujian dengan race detector tidak lagi menunjukkan masalah yang sama.
Bukti kedua: crash pada proses server
Race detector membuktikan adanya race condition, tetapi itu belum cukup untuk menyimpulkan layanan benar-benar dapat mengalami DoS. Karena itu, kami melakukan pengujian lanjutan pada binary biasa, tanpa race detector. Hasilnya: pada lingkungan yang rentan, proses server dapat berhenti dengan pesan `fatal error: concurrent map writes`. Kami juga memeriksa koneksi baru untuk membedakan proses yang benar-benar mati dari request yang sekadar ditolak.

Gambar 7. Pada Go 1.25.1, proses server berhenti dengan fatal error `concurrent map writes`.

Gambar 8. Hasil serupa ditemukan pada Go 1.26.10, sebelum perbaikan keamanan dirilis.

Gambar 9. Go 1.27.4 tetap berjalan setelah 900 request uji per varian, tanpa crash yang teramati.
Temuan tambahan: risiko supply chain saat build dengan cgo
Selain masalah net/http, rilis ini memperbaiki sebelas CVE yang berkaitan dengan proses build. Pada kelas masalah ini, risikonya muncul ketika developer membangun paket cgo yang tidak tepercaya. Flag tertentu bisa diteruskan ke compiler atau linker dengan cara yang tidak semestinya. Sebagai contoh, kami memeriksa CVE-2026-97035, yang berhubungan dengan validasi flag Clang.

Gambar 10. Perbandingan validasi flag cgo: perilaku sebelum patch dan penolakan pada Go 1.27.4.
Perbaikan lain mencakup validasi berbagai opsi compiler, linker, file objek, pkg-config, dan directive cgo (CVE-2026-97033 hingga CVE-2026-97043 sebagaimana dicatat dalam dokumen riset). Meski bukan jalur serangan yang sama dengan CVE-2026-97054, rangkaian pembaruan ini mengingatkan bahwa keamanan dependency juga penting pada tahap build.
Dampak dan sistem yang perlu diperiksa
· Dampak yang kami buktikan adalah denial-of-service pada proses server. Dalam konfigurasi yang rentan, request HTTP tanpa login dapat memicu race condition yang berujung crash. Ini bukan berarti setiap request berukuran besar pasti menyebabkan crash; hasilnya bergantung pada waktu eksekusi dan bagaimana aplikasi memproses request.
· Menurut advisory OSV, versi terdampak mencakup rilis sebelum Go 1.26.11 serta seri 1.27 sebelum 1.27.4. Versi lama yang sudah di luar masa dukungan, termasuk Go 1.25, perlu dimigrasikan ke versi yang mendapat perbaikan keamanan. Periksa pula paket Go yang digunakan saat membangun binary, bukan hanya versi Go yang terpasang saat ini di server.
· Pemeriksaan sebaiknya memprioritaskan server HTTP/1 yang menggunakan MaxBytesReader atau MaxBytesHandler, khususnya bersama ReverseProxy atau handler lain yang membaca request body dan menulis respons secara concurrent. Kehadiran fungsi tersebut merupakan petunjuk untuk audit, bukan bukti bahwa aplikasi pasti rentan dieksploitasi.
· Ketika pengujian ini selesai, belum ada skor CVSS NVD dan belum ditemukan status CISA KEV atau PoC publik. Kami sengaja tidak menetapkan skor sendiri sebagai skor resmi. Yang sudah terbukti dalam lab adalah potensi penghentian seluruh proses layanan pada konfigurasi yang memenuhi kondisi.
Mitigasi dan langkah pemeriksaan
· Prioritas utama adalah menggunakan Go 1.26.11 atau yang lebih baru pada jalur 1.26, atau Go 1.27.4 atau yang lebih baru pada jalur 1.27, lalu rebuild dan redeploy semua service yang terdampak. Update toolchain tanpa membangun ulang binary aplikasi yang sudah berjalan tidak otomatis memperbaiki aplikasi tersebut.
· Untuk pipeline CI/CD, tinjau dependency cgo dan batasi build dari source yang tidak tepercaya. Sebelas CVE terkait build menunjukkan bahwa proses kompilasi sendiri perlu diperlakukan sebagai bagian dari attack surface.
· Jika upgrade belum dapat dilakukan, batasi ukuran request body di reverse proxy atau load balancer di depan aplikasi sebagai langkah sementara. Terapkan batas yang lebih ketat daripada batas internal aplikasi dan uji perilaku penolakan request. Mitigasi ini membantu mengurangi paparan, tetapi bukan pengganti patch.
· Cari penggunaan MaxBytesHandler, MaxBytesReader, dan ReverseProxy pada source code. Pantau error `concurrent map writes`, restart berulang, serta gangguan availability pada API gateway. Jika ada indikasi masalah, cocokkan waktu kejadian dengan access log dan log aplikasi sebelum menyimpulkan penyebabnya.
Catatan dari proses reproduksi
· Dalam pengujian concurrency, crash tidak selalu mudah direproduksi karena bergantung pada timing antar-goroutine. Itulah alasan kami memakai race detector terlebih dahulu: alat ini membantu menunjukkan masalah pada akses data yang sama, bahkan ketika proses belum berhenti.
· Untuk mengukur dampak nyata, kami kemudian menguji aplikasi tanpa race detector dan membandingkan hasil antarversi Go. Fokusnya adalah memastikan apakah masalah berhenti pada peringatan race, atau dapat memengaruhi availability layanan.
· Koneksi yang ditutup setelah respons HTTP 413 dan header `Connection: close` merupakan perilaku yang wajar. Karena itu, koneksi terputus tidak cukup untuk disebut DoS. Dalam lab, kami melakukan pemeriksaan terpisah untuk memastikan apakah proses server masih menerima koneksi baru.
· Pengujian paralel juga dapat dipengaruhi batas socket buffer dan karakteristik sistem operasi. Kondisi lingkungan uji perlu dicatat agar error pada sisi klien tidak keliru dianggap sebagai bug pada server.
· Hal terpenting dari reproduksi ini adalah membedakan tiga hal: data race yang terdeteksi, request yang ditolak secara normal, dan proses server yang benar-benar crash. Ketiganya memiliki makna keamanan yang berbeda.
Referensi teknis
· https://groups.google.com/g/golang-announce/c/iY8TY0wWgbM — pengumuman rilis
· https://go.dev/issue/82563 + https://go.dev/cl/862185 — isu & patch resmi
· https://github.com/golang/go/commit/705bd8c — commit master
· https://pkg.go.dev/vuln/GO-2026-6859 — advisory stdlib (alias CVE-2026-97054)
· https://nvd.nist.gov/vuln/detail/CVE-2026-97054 — skor NVD menyusul

